import { fabric } from 'fabric';
import { IEditor } from '@/types/global';
import { BoardSyncEvent, JsonOption } from '@/utils/Const.ts';

class LockPlugin {
  canvas: fabric.Canvas;
  editor: IEditor;
  static pluginName: string = 'LockPlugin';
  static apis: string[] = ['lockElement', 'unLockElement', 'lockSelection'];

  constructor(canvas: fabric.Canvas, editor: IEditor) {
    this.canvas = canvas;
    this.editor = editor;
  }

  // 锁定画布元素
  lockElement() {
    const targets = this.canvas.getActiveObjects();
    const target = this.canvas.getActiveObject();
    if (targets.length === 0 && !target) return;
    const oldElementsJson: any[] = [];
    const newElementsJson: any[] = [];
    if (target.type === 'activeSelection') {
      const matrix = target.calcTransformMatrix();
      targets.forEach((item) => {
        // 首先保存旧状态
        const objectPosition = { x: item.left, y: item.top };
        const finalPosition = fabric.util.transformPoint(
          objectPosition,
          matrix,
        );
        const oldItemJson = item.toJSON(JsonOption);
        oldItemJson.top = finalPosition.y;
        oldItemJson.left = finalPosition.x;
        oldElementsJson.push(oldItemJson);
        // 锁定元素
        this.lockOneElement(item);
        // 最后保存锁定后的新状态
        const newItemJson = item.toJSON(JsonOption);
        newItemJson.top = finalPosition.y;
        newItemJson.left = finalPosition.x;
        newElementsJson.push(newItemJson);
      });
      target.set('lockMovementX', true);
      target.set('lockMovementY', true);
      target.set('hasControls', false);
      target.lock = true;
    } else {
      oldElementsJson.push(target.toJSON(JsonOption));
      this.lockOneElement(target);
      newElementsJson.push(target?.toJSON(JsonOption));
    }
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [...oldElementsJson],
      newElements: [...newElementsJson],
    });
    this.canvas.renderAll();
  }

  // 解锁画布元素
  unLockElement() {
    const targets = this.canvas.getActiveObjects();
    const target = this.canvas.getActiveObject();
    if (targets.length === 0 && !target) return;
    const oldElementsJson: any[] = [];
    const newElementsJson: any[] = [];
    if (target.type === 'activeSelection') {
      const matrix = target.calcTransformMatrix();
      targets.forEach((item) => {
        // 首先保存旧状态
        const objectPosition = { x: item.left, y: item.top };
        const finalPosition = fabric.util.transformPoint(
          objectPosition,
          matrix,
        );
        const oldItemJson = item.toJSON(JsonOption);
        oldItemJson.top = finalPosition.y;
        oldItemJson.left = finalPosition.x;
        oldElementsJson.push(oldItemJson);
        // 锁定元素
        this.unlockOneElement(item);
        // 最后保存锁定后的新状态
        const newItemJson = item.toJSON(JsonOption);
        newItemJson.top = finalPosition.y;
        newItemJson.left = finalPosition.x;
        newElementsJson.push(newItemJson);
      });
      target.set('lockMovementX', false);
      target.set('lockMovementY', false);
      target.set('hasControls', true);
      target.lock = false;
    } else {
      oldElementsJson.push(target.toJSON(JsonOption));
      this.unlockOneElement(target);
      newElementsJson.push(target?.toJSON(JsonOption));
    }
    // targets.forEach((item) => {
    //   oldElementsJson.push(item.toJSON(JsonOption));
    //   item.set('lockMovementX', false);
    //   item.set('lockMovementY', false);
    //   item.set('hasControls', true);
    //   item.set('dirty', false);
    //   item.lock = false;
    //   if (item.type === 'textbox') {
    //     item.set('editable', false);
    //   } else if (item.type === 'path') {
    //     item.set('erasable', false);
    //   }
    //   newElementsJson.push(item.toJSON(JsonOption));
    // });
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [...oldElementsJson],
      newElements: [...newElementsJson],
    });
    this.canvas.renderAll();
  }

  lockSelection() {
    const activeSelection = this.canvas.getActiveObject();
    if (!activeSelection) return;
    if (activeSelection.type !== 'activeSelection') {
      this.lockElement();
      return;
    }
    const unlockObjects = activeSelection.getObjects().filter((item: any) => {
      return !item.lock;
    });
    if (unlockObjects.length === 0) {
      activeSelection.set('lockMovementX', true);
      activeSelection.set('lockMovementY', true);
      activeSelection.set('hasControls', false);
      activeSelection.set('selectable', false);
      activeSelection.lock = true;
    } else if (unlockObjects.length === 1) {
      this.canvas.setActiveObject(unlockObjects[0]);
    } else if (
      unlockObjects.length > 1 &&
      unlockObjects.length < activeSelection.getObjects().length
    ) {
      const { canvas } = this;
      // 编程创建多选
      canvas.discardActiveObject();
      const newActiveSelection = new fabric.ActiveSelection(unlockObjects, {
        canvas: canvas,
      });
      canvas.setActiveObject(newActiveSelection);
      canvas.requestRenderAll();
    }
    this.canvas.renderAll();
  }

  lockOneElement(el) {
    el.set('lockMovementX', true);
    el.set('lockMovementY', true);
    el.set('hasControls', false);
    el.set('dirty', true);
    el.lock = true;
    if (el.type === 'textbox') {
      el.set('editable', false);
    } else if (el.type === 'path') {
      el.set('erasable', false);
    }
  }

  unlockOneElement(el) {
    el.set('lockMovementX', false);
    el.set('lockMovementY', false);
    el.set('hasControls', true);
    el.set('dirty', false);
    el.lock = false;
    if (el.type === 'textbox') {
      el.set('editable', true);
    } else if (el.type === 'path') {
      el.set('erasable', true);
    }
  }
}

export default LockPlugin;
